/*
通用OTDR

2021.7.28 by Menglong Wu
*/
#include <autoconfig.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#include <sys/ioctl.h>

#include <assert.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <stdio.h>

#include "proginfo.h"
// #include "fpga-tr700.h"
#include "printl.h"
#include "port.h"
#include "fpga-common.h"
#include "fpga-private.h"
#include "interface/protocal-otdr.h"


// #define ENV_PRINT_W(fmt, ...)                             \
// 		_ctstprint(C_WARN, C_NORMAL, fmt, ##__VA_ARGS__); \


#include "encode-otdr.h"
#define DATA_FLAG     0x23
// #define SPI_IOC_MAGIC 'k' // 这个定义放在spi/spidev.h

#define SPI_TP_BEGIN  _IOR(SPI_IOC_MAGIC, 5, __u8)
#define SPI_TP_COMMIT _IOR(SPI_IOC_MAGIC, 6, __u8)

extern int env_otdr_dbg_level;

#define this_dbg(fmt, ...)                                           \
    if (env_otdr_dbg_level) {                                        \
	PRINTL(OTDR_DBG_LEVEL, C_DEBUG fmt C_NORMAL, ##__VA_ARGS__); \
    }
// #define this_dbg(fmt, ...)

struct _fpga_test_param_tx_2016
{
    unsigned short laser;  ///< 激光器通道
    unsigned short pulse;
    // unsigned short dist;
#if 1 || CONFIG_PROTOCAL_TR600_SPI
    unsigned char freq;
    unsigned char adopt_pt;
    short         add_cnt;
#endif
    // unsigned short add_ms;
    char power;
    char amp;
    char apd_vol;
    char slot;
    char ch;  ///< 光开关通道
    char unuse1, unuse2, unuse3;
};


// TODO 虽然这个是最找的，但已经停用了，所以吧他分离到bsp-tr600-imx6-2016.c
struct otdr_driver_data_2016
{
    char *otdr_cache;
};

static inline char *get_cache(struct fpga_dev *dev)
{
    // printf("dev->interface %x\r\n", dev->interface);
    // printf("dev->interface->prv %x\r\n", dev->interface->private_data);
    // printf("dev->interface->drv %x\r\n", dev->interface->driver_data);
    struct otdr_driver_data_2016 *p = (struct otdr_driver_data_2016 *)fpga_if_get_driver_data(dev->interface);
    // printf("p = %x\r\n", p);
    return p->otdr_cache;
}
/*
老协议 OTDR start 发送参数是0
*/
int cb_fpga_otdr_start_2016(struct fpga_dev *dev)
{
    fpga_if_set_gpio(dev, 1, 1);

    char rbuf[MIN_RX_PACK_SIZE];


    int ret = fpga_send_data(dev,
                             OTDR_START,
                             0,
                             0,
                             rbuf,
                             sizeof(rbuf));
    return ret;
}

int cb_fpga_otdr_isfinish_2016(struct fpga_dev *dev, bool *val)
{
    unsigned char ack;
    // struct otdr_start tbuf;
    char rbuf[MIN_RX_PACK_SIZE];
    // tbuf.ch = dev->ch;
    fpga_send_data(dev,
                   OTDR_IS_FINISH,
                   NULL,
                   0,
                   rbuf,
                   sizeof(rbuf));
    ack = ACK_CODE(rbuf);
    switch (ack) {
    case 0xaa:
	dev->checksum  = _STREAM_TO_32(&rbuf[CHKSUM_OFFSET]);
	dev->cum_count = _STREAM_TO_16(&rbuf[CUM_COUNT_OFFSET]);
	*val           = true;
	return 0;
    case 0x55:
	dev->checksum  = 0;
	dev->cum_count = 0;
	*val           = false;
	// ENV_PRINT_E("Error\r\n");
	return 0;
    default:
	return -1;
    }
}

struct _dist_sample_freq
{
    /*
      正常情况下，
      每个量程下的采用频率是固定的，如不用该对应关系则用
      struct _list_self_sample_freq 描述
    */
    unsigned long dist;
    unsigned char sample_freq;
};
#define FREQ_800M (0x90)
#define FREQ_400M (0x88)
#define FREQ_200M (0x84)
#define FREQ_100M (0x82)
#define FREQ_50M  (0x80)
#define FREQ_25M  (0x7e)
#define FREQ_12M  (0x7c)

static const struct _dist_sample_freq _sample_freq[] = {
    { 300, FREQ_800M },
    { 1000, FREQ_800M },
    { 5000, FREQ_400M },
    { 10000, FREQ_200M },
    { 30000, FREQ_100M },
    { 60000, FREQ_50M },
    { 100000, FREQ_25M },
    { 180000, FREQ_12M },
    { 200000, FREQ_12M },
    { 0, 0 },
};

char _encode_dist_2_sample_freq(struct fpga_test_param *val)
{
    // 查找对应量程需要使用的频率
    struct _dist_sample_freq *tlist = (struct _dist_sample_freq *)_sample_freq;

    while (tlist->dist) {
	if (tlist->dist == val->dist) {
	    break;
	}
	tlist++;
    }
    assert(tlist->dist != 0);

    if (tlist->dist == 0) {
	// 参数错误采用默认值
	PRINTE("Error Param distance\r\n");
	return FREQ_800M;
    }
    return tlist->sample_freq;
}


struct _list_self_sample_freq
{
    int val;  // 采样频率描述值，单位为 MHz
    /*
      采样频率编码值，数据类型与
      struct _fpga_test_param_tx -> freq 一致
    */
    unsigned char encode;
};

static const struct _list_self_sample_freq _l_sample_freq[] = {
    { 800, FREQ_800M },
    { 400, FREQ_400M },
    { 200, FREQ_200M },
    { 100, FREQ_100M },
    { 50, FREQ_50M },
    { 25, FREQ_25M },
    { 12, FREQ_12M },
    { 0, 0 },
};
// 自定义采样频率
char _this_encode_self_sample_freq(struct fpga_test_param *val)
{
    struct _list_self_sample_freq *tlist = (struct _list_self_sample_freq *)_l_sample_freq;

    while (tlist->val) {
	if (val->sample_freq == tlist->val) {
	    break;
	}
	tlist++;
    }
    assert(tlist->val != 0);

    if (tlist->val == 0) {
	// 参数错误采用默认值
	PRINTE("Param Error\r\n");
	return FREQ_800M;
    }
    return tlist->encode;
}

/*
  50MHz 采样时钟为基准，得到其他频率的分频系数

  Note
  高于 50MHz 不是采用倍频，而是移相，所以分频系数与 50MHz 相同
 */

struct _dist_div
{
    unsigned long dist;
    unsigned long div;
};
#define FREQ_800M_DIV (0)
#define FREQ_400M_DIV (0)
#define FREQ_200M_DIV (0)
#define FREQ_100M_DIV (0)
#define FREQ_50M_DIV  (0)
#define FREQ_25M_DIV  (1)
#define FREQ_12M_DIV  (2)
static const struct _dist_div _dd[] = {
    { 300, FREQ_800M_DIV },
    { 1000, FREQ_800M_DIV },
    { 5000, FREQ_400M_DIV },
    { 10000, FREQ_200M_DIV },
    { 30000, FREQ_100M_DIV },
    { 60000, FREQ_50M_DIV },
    { 100000, FREQ_25M_DIV },
    { 180000, FREQ_12M_DIV },
    { 200000, FREQ_12M_DIV },
    { 0, 0 },
};


short _encode_dist_2_pulse(struct fpga_test_param *val)
{
    // 5ns 10ns 采用自然编码
    if (val->pulse < 20) {
	return val->pulse;
    }
    // TODO 开发期间过滤掉非20ns的倍数
    const struct _dist_div *tlist = (struct _dist_div *)_dd;

    while (tlist->dist) {
	if (tlist->dist == val->dist) {
	    break;
	}
	tlist++;
    }
    assert(tlist->dist != 0);

    if (tlist->dist == 0) {
	// 参数错误采用默认值
	PRINTE("Error Param distance\r\n");
	return 10;
    }
    return (val->pulse / 20) >> tlist->div | 0x8000;
}

struct _list_self_pulse
{
    int freq;  // 采样频率描述值，单位为 MHz
    /*
      采样频率编码值，数据类型与
      struct _fpga_test_param_tx -> freq 一致
    */
    unsigned char div;
};


static const struct _list_self_pulse _l_self_pulse[] = {
    { 800, FREQ_800M_DIV },
    { 400, FREQ_400M_DIV },
    { 200, FREQ_200M_DIV },
    { 100, FREQ_100M_DIV },
    { 50, FREQ_50M_DIV },
    { 25, FREQ_25M_DIV },
    { 12, FREQ_12M_DIV },
    { 0, 0 },
};

static short _this_encode_self_pulse(struct fpga_test_param *val)
{
    // 5ns 10ns 采用自然编码
    if (val->pulse < 20) {
	return val->pulse;
    }
    // TODO 开发期间过滤掉非20ns的倍数
    struct _list_self_pulse *tlist = (struct _list_self_pulse *)_l_self_pulse;

    while (tlist->freq) {
	if (tlist->freq == val->sample_freq) {
	    break;
	}
	tlist++;
    }
    assert(tlist->freq != 0);

    if (tlist->freq == 0) {
	// 参数错误采用默认值
	PRINTE("Error Param distance\r\n");
	return 10;
    }
    // return 0x8001;//
    return (val->pulse / 20) >> tlist->div | 0x8000;
}

#define get_offset(type, member) (unsigned long)(&(((type *)0)->member))

#if 0
void test()
{
	struct _fpga_test_param_tx_2016 tmp1;
	printf("...........................\r\n");
	printf("%d\r\n", sizeof(struct _fpga_test_param_tx_2016));
	printf("laser\t\t%d\r\n", get_offset(struct _fpga_test_param_tx_2016, laser));
	printf("pulse\t\t%d \r\n", get_offset(struct _fpga_test_param_tx_2016, pulse));
	printf("freq\t\t%d \r\n", get_offset(struct _fpga_test_param_tx_2016, freq));
	printf("adopt_pt\t\t%d \r\n", get_offset(struct _fpga_test_param_tx_2016, adopt_pt));
	printf("add_cnt\t\t%d \r\n", get_offset(struct _fpga_test_param_tx_2016, add_cnt));
	printf("power\t\t%d \r\n", get_offset(struct _fpga_test_param_tx_2016, power));
	printf("amp\t\t%d \r\n", get_offset(struct _fpga_test_param_tx_2016, amp));
	printf("apd_vol\t\t%d \r\n", get_offset(struct _fpga_test_param_tx_2016, apd_vol));
	printf("slot\t\t%d \r\n", get_offset(struct _fpga_test_param_tx_2016, slot));
	printf("ch\t\t%d \r\n", get_offset(struct _fpga_test_param_tx_2016, ch));
}
#endif

#if 0
void show(struct fpga_test_param *p)
{
printf("en_hw_dist \t\t %x\r\n", p->en_hw_dist);
printf("dist \t\t %x\r\n", p->dist);
printf("laser_freq \t\t %x\r\n", p->laser_freq);
printf("en_hw_pulse \t\t %x\r\n", p->en_hw_pulse);
printf("pulse \t\t %x\r\n", p->pulse);
printf("sample_freq \t\t %x\r\n", p->sample_freq);
printf("en_hw_adopt_pt \t\t %x\r\n", p->en_hw_adopt_pt);
printf("adopt_pt \t\t %x\r\n", p->adopt_pt);
printf("en_hw_add_cnt \t\t %x\r\n", p->en_hw_add_cnt);
printf("add_cnt \t\t %x\r\n", p->add_cnt);
printf("en_hw_add_ms \t\t %x\r\n", p->en_hw_add_ms);
printf("add_ms \t\t %x\r\n", p->add_ms);
printf("amp \t\t %x\r\n", p->amp);
printf("en_hw_amp \t\t %x\r\n", p->en_hw_amp);
printf("hw_amp \t\t %x\r\n", p->hw_amp);
printf("apd_vol \t\t %x\r\n", p->apd_vol);
printf("en_hw_apd_vol \t\t %x\r\n", p->en_hw_apd_vol);
printf("hw_apd_vol \t\t %x\r\n", p->hw_apd_vol);
printf("power \t\t %x\r\n", p->power);
printf("isrun \t\t %x\r\n", p->isrun);
printf("laser_ch \t\t %x\r\n", p->laser_ch);
printf("panel_ch \t\t %x\r\n", p->panel_ch);
}
#endif
static int _fpga_otdr_param(struct fpga_dev *dev, struct fpga_test_param *val)
{
    // PrintfMemory((uint8_t*)val, sizeof(struct fpga_test_param));
    // show(val);
    assert(dev != NULL);
    assert(dev->desc == dev_desc);

    struct _fpga_test_param_tx_2016 tbuf;

    /*
      当 sample_freq 未指定时使用默认采样频率，并计算脉冲宽度编码，
      否则使用自定义采样频率
    */
    // if (val->en_hw_pulse == false) {
    // 	tbuf.pulse = _encode_pulse(val);
    // }
    // else {
    // 	tbuf.pulse = _encode_self_pulse(val);
    // }
    // if (val->en_hw_dist == false) {
    // 	tbuf.dist = _encode_dist(val);
    // }
    // else {
    // 	tbuf.dist = _encode_self_dist(val);
    // }


    if (val->sample_freq == 0) {
	// TODO 完成这两项
	tbuf.pulse = _encode_dist_2_pulse(val);  // val->pulse;
	tbuf.freq  = _encode_dist_2_sample_freq(val);
    }
    else {
	tbuf.pulse = _this_encode_self_pulse(val);
	tbuf.freq  = _this_encode_self_sample_freq(val);
    }


    tbuf.laser    = _encode_laser(val);
    tbuf.adopt_pt = _encode_adopt(val);
    tbuf.add_cnt  = _encode_add_cnt(val);
    tbuf.power    = _encode_power(val);


    // printf("val->ms = %d\n", val->add_ms);
    // tbuf.add_ms = _encode_add_ms(val);
    if (val->en_hw_amp) {
	tbuf.amp = val->hw_amp;
    }
    else {
	tbuf.amp = _encode_amp(val);
    }

    if (val->en_hw_apd_vol) {
	tbuf.apd_vol = val->hw_apd_vol;
    }
    else {
	tbuf.apd_vol = _encode_apd_vol(val);
    }
    tbuf.slot   = _encode_slot(val);
    tbuf.ch     = _encode_ch(val);
    tbuf.unuse1 = 0;
    tbuf.unuse2 = 0;
    tbuf.unuse3 = 0;

    // tbuf.freq = 0x80;
    // tbuf.adopt_pt =0x08;
    // tbuf.add_cnt = 0x03e8;

#if 2016
    // this_dbg("    laser             %4.4x\n", tbuf.laser);
    // this_dbg("    pulse             %4.4x\n", tbuf.pulse);
    // this_dbg("    freq              %2.2x\n", tbuf.freq);
    // this_dbg("    adopt_pt          %2.2x\n", tbuf.adopt_pt);
    // this_dbg("    add_cnt           %4.4x\n", tbuf.add_cnt);
    // this_dbg("    power             %2.2x\n", tbuf.power);
    // this_dbg("    amp               %2.2x\n", tbuf.amp);
    // this_dbg("    apd_vol           %2.2x\n", tbuf.apd_vol);
    // this_dbg("    slot              %2.2x\n", tbuf.slot);
    // this_dbg("    ch                %2.2x\n", tbuf.ch);
    // this_dbg("    unuse1            %2.2x\n", tbuf.unuse1);
    // this_dbg("    unuse2            %2.2x\n", tbuf.unuse2);
    // this_dbg("    unuse3            %2.2x\n", tbuf.unuse3);
#else

    printf("Encode:\r\n");
    printf("    laser             %4.4x\n", tbuf.laser);
    printf("    pulse             %4.4x\n", tbuf.pulse);
    printf("    dist              %4.4x\n", tbuf.dist);
    printf("    add_ms            %4.4x\n", tbuf.add_ms);
    printf("    power             %2.2x\n", tbuf.power);
    printf("    amp               %2.2x\n", tbuf.amp);
    printf("    apd_vol           %2.2x\n", tbuf.apd_vol);
    printf("    slot              %2.2x\n", tbuf.slot);
    printf("    ch                %2.2x\n", tbuf.ch);
    printf("    unuse1            %2.2x\n", tbuf.unuse1);
    printf("    unuse2            %2.2x\n", tbuf.unuse2);
    printf("    unuse3            %2.2x\n", tbuf.unuse3);
#endif
    dev->ch = tbuf.ch;

    char rbuf[MIN_RX_PACK_SIZE];
    // ENV_PRINT_W("TODO MIN_RX_PACK_SIZE 不是TR600 返回长度");
    unsigned char ack;
    unsigned int  err_times = 0;
    // for (int retry = 0; retry < RETRY; retry++) {
    // 每个循环耗时5.4ms，最多等待1s
    for (int retry = 0; retry < 3; retry++) {
	_fpga_transfer(dev,
	               OTDR_PARAM,
	               (char *)&tbuf,
	               sizeof(struct _fpga_test_param_tx_2016),
	               rbuf,
	               ARRAY_SIZE(rbuf));
	ack = ACK_CODE(rbuf);
	switch (ack) {
	case 0xaa:
	    // printf("%s() OK\r\n", __FUNCTION__);
	    // usleep(10000);// FPGA控制光耦
	    goto _AnalyseOther;
	case 0x55:
	    // ENV_PRINT_W("Error\r\n");
	    err_times++;
	    break;
	default:
	    ENV_PRINT_E("unknow\r\n");
	    break;
	}
	usleep(10000);
    }
    if (err_times) {
	ENV_PRINT_W("Error times %d\r\n", err_times);
    }
    ENV_PRINT_E("retry time out\r\n");
    return -1;
_AnalyseOther:;
    if (err_times) {
	ENV_PRINT_W("Error times %d\r\n", err_times);
    }
    /* todo TR700需要返回
     sample_freq 采样频率 MHz
     adopt_pt  采样点数
     */

    printf("buf 12 %x \n", *(rbuf + 12));
    // *(rbuf + 11)  = 0x11;
    // *(rbuf + 12)  = 0x12;
    // *(rbuf + 13)  = 0x13;
    // *(rbuf + 14)  = 0x14;
    // *(rbuf + 15)  = 0x15;


    // PrintfMemory(rbuf, MIN_RX_PACK_SIZE);

    dev->sample_freq = _decode_freq(rbuf);
    dev->adopt_pt    = _decode_adopt_pt(rbuf);
    // printf("Decode:\r\n");
    // printf("    sample_freq       %d \n", (int)dev->sample_freq);
    // printf("    adopt_pt          %d \n", (int)dev->adopt_pt);
    return 0;
}

int cb_fpga_otdr_write_regs_2016(struct fpga_dev *dev, unsigned int base_addr, unsigned int *regs, int len)
{
    // 忽略任何base
    mutex_lock(&dev->mutex);
    int ret = _fpga_otdr_param(dev, (struct fpga_test_param *)regs);
    mutex_unlock(&dev->mutex);

// 如果以后写FPGA的同事能力提高后再真正实现寄存器地址读写
#if 0
	// FPGA只支持某几个地址
	switch(base_addr) {
		case xx:
		fpga_send_data(...);
		break;
	}
	// FPGA支持任何地址
	fpga_send_data(...);
#endif
    return ret;
}


static int _otdr_data_swap(unsigned char *buf, int len)
{
    unsigned char *pchar = (unsigned char *)buf;
    char           tmp[4];

    // printf("-------------ffffffffff\r\n");
    // printf("--- %x %x %x %x\r\n",
    // pchar[0], pchar[1], pchar[2], pchar[3]);
    for (int i = 0; i < len;) {
#if 0
		if (pchar[0] != DATA_FLAG) {
			ENV_PRINT_E("error otdr data index %i\n", i);
			printf("error otdr data index %i\n", i);
			// debug
			if (i >= 100) {
				printf("Before 100 byte:\r\n");
				PrintfMemory((uint8_t *)pchar - 100, 100);
			}
			if (i < len - 100) {
				printf("After 100 byte:\r\n");
				PrintfMemory((uint8_t *)pchar, 100);
			}
			// End debug
			return -1;
		}
#endif
	tmp[0] = pchar[0];
	tmp[1] = pchar[1];
	tmp[2] = pchar[2];
	tmp[3] = pchar[3];


	// pchar[3] = 0;
	// pchar[2] = tmp[1];
	// pchar[1] = tmp[2];
	// pchar[0] = tmp[3];

	// tmp[3] = 0;
	// pchar[3] = tmp[0];
	// pchar[2] = tmp[1];
	// pchar[1] = tmp[2];
	// pchar[0] = tmp[3];

	tmp[0]   = 0;
	pchar[3] = tmp[0];
	pchar[2] = tmp[1];
	pchar[1] = tmp[2];
	pchar[0] = tmp[3];


	pchar += 4;
	i += 4;
    }
    return 0;
}
extern unsigned long __checksum(unsigned char *data, int len);


static int _cb_fpga_read_otdr_data(
	struct fpga_dev *dev,
	unsigned char   *otdr_data,
	unsigned long    len,
	unsigned long   *rlen)
{
    assert(dev != NULL);
    assert(dev->desc == dev_desc);
    // assert(dev->otdr_cache != NULL);
    assert(len == 16000 * 4 || len == 32000 * 4 || len == 64000 * 4 ||
           len == 128000 * 4);
    // char *rbuf = dev->otdr_cache;
    char *rbuf = get_cache(dev);
    // char *rbuf = otdr_data;
    /*
     * OTDR 数据格式，第一个0x23开头，后面每 4 byte为1数据点，每数据点
     * 0x23开头 0x23 | 0x23 xx xx xx | 0x23 xx xx xx | 0x23 xx xx xx
     *
     *         otdr_cache 最终存储的内容
     * |    0 byte             32000*4| 4000 |
     * |    OTDR 数据                 | 冗余 |
     * 后面的冗余内容是为了处理OTDR数据偏移而特意多读的
     */
    // do_otdr_test_led(0);
    fpga_if_set_gpio(dev, 1, 0);

    int find_23 = 0;
    this_dbg("%s() search 'DATA_FLAG' \r\n", __FUNCTION__);

    /*
    步骤1：请求数据
    FPGA有BUG，经常返回内容格式“错位”
    本步骤除了_fpga_transfer外，其他都是为了调试查错的
    */
    // 逐个寻找标志字符，
    mutex_lock(&dev->mutex);
    // 这个for循环可以从3改成1
#if 1
    for (int j = 0; j < 3; j++) {
	/*
	 * 发送请求，这个不能少，只读取 1byte，寻找标志
	 */
	_fpga_transfer(dev,
	               OTDR_ROTDR,
	               &dev->ch,
	               sizeof(dev->ch),
	               //    dev->otdr_cache,
	               get_cache(dev),
	               1);
	/*
	逐个byte读取，在一定范围内寻找otdr数据帧头，
	找到后就连快速读取后面的数据
	*/
#define CHECK_SERIAL (30)  // 在数据头N个字节里寻找标志

	for (int i = 0; i < CHECK_SERIAL; i++) {
	    //            printf("%s() %d\r\n", __FUNCTION__,
	    //            __LINE__);
	    // if (dev->otdr_cache[0] == DATA_FLAG) {
	    if (get_cache(dev)[0] == DATA_FLAG) {
		find_23 = 1;
		goto _SerialRead;
	    }
	    // _read_otdr_1(
	    // 		dev,
	    // 		(unsigned char *)(dev->otdr_cache),
	    // 		1);
	    _read_otdr_1(
		    dev,
		    (unsigned char *)(get_cache(dev)),
		    1);
	}
    }
_SerialRead:;
    if (find_23 == 0) {
	ENV_PRINT_E(
		"otdr data errr: can't find flag 'DATA_FLAG' (0-100 byte) %2.2x %2.2x %2.2x %2.2x\r\n",
		*(get_cache(dev) + 0),
		*(get_cache(dev) + 1),
		*(get_cache(dev) + 2),
		*(get_cache(dev) + 3));
	mutex_unlock(&dev->mutex);
	return -1;
    }
#endif


    /*
    步骤2：读取后面的所有数据
    FPGA数据发送计数器未清0，可能导致不响应之后的数据，解决方法：
    1、otdr_cache长度最好远大于FPGA返回长度，保证把FPGA读空，后面的数据是全0x00或0xff。
    2、每次和FPGA握手时首先度全远大于FPGA返回长度；
    目前只使用方案1，方案2只是验证FPGA有错误。
    后来FPGA做了修改，在每次收到OTDR_START请求后清空计数器；最好的做法是CS上身边沿清除
    */

    // Fix LS2K: 不支持 cs_change = 0,所以必须一次性读取所有数据
    // _read_otdr_serial(dev, (unsigned char *)(dev->otdr_cache + 1), len, 0);
    _read_otdr_serial(dev, (unsigned char *)(get_cache(dev) + 1), len, 0);

    if (env_dbg_rx) {
	this_dbg("%s() peek receive data", __FUNCTION__);
	PrintfMemory((uint8_t *)rbuf, 16);
    }
    // 拷贝到调用者
    memcpy_char((char *)otdr_data, (char *)(rbuf + 0), len);
    mutex_unlock(&dev->mutex);


    /*
    数据都在 otdr_data 里，下面的数据double otdr_cache 的锁不再有效
    整个系统最慢的地方就在这里，对数据交换、高Byte清0
    */
    __attribute__((unused)) int swap_err = _otdr_data_swap(otdr_data, len);
    // _print_otdr_data((unsigned long *)otdr_data, len / 4);
    brief_print_data((unsigned long *)otdr_data, len / 4);
#if defined(CONFIG_CHK_OTDR_FLAG) && !defined(CONFIG_USE_CKSUM)
    if (swap_err == -1) {
	return -1;
    }
    return 0;
#else
    if (swap_err == -1) {
	printf("otdr swap error\r\n");
	return -1;
    }
    unsigned long sum = 0;
    if (env_unuse_cksum == 0) {
	sum = __checksum(otdr_data, len);
	if ((unsigned int)(dev->checksum & 0xffffffff) ==
	    (unsigned int)(sum & 0xffffffff))
	{
	    this_dbg("%s() check sum OK\r\n", __FUNCTION__);
	    return 0;
	}
	else {
	    ENV_PRINT_W("check sum error cksum [%lx] otdr [%lx]\n",
	                (long)(dev->checksum),
	                (long)(sum));
	    return -1;
	}
    }
    else {
	// printf("env_unuse_cksum = 1\r\n");
	return 0;
    }
#endif
}


int _cb_fpga_otdr_probe(struct fpga_dev *dev)
{
    struct priv_otdr_data        *pdata_bsp = fpga_if_get_bsp_data(dev->interface);
    struct otdr_driver_data_2016 *pnew      = malloc(sizeof(struct otdr_driver_data_2016));

    printf("pdata_bsp->cache_len %x %d\r\n", (unsigned int)pdata_bsp, pdata_bsp->cache_len);
    pnew->otdr_cache = (char *)malloc(pdata_bsp->cache_len);
    printf("malloc %x\r\n", (unsigned int)pnew);
    fpga_if_set_driver_data(dev->interface, pnew);
    get_cache(dev);
    return 0;
}


int _cb_fpga_otdr_release(struct fpga_dev *dev)
{
    struct otdr_driver_data_2016 *pdata_drv = fpga_if_get_driver_data(dev->interface);
    if (pdata_drv->otdr_cache) {
	free(pdata_drv->otdr_cache);
	pdata_drv->otdr_cache = NULL;
    }
    return 0;
}


static struct priv_otdr_data data_32k = {
    .cache_len   = 32000 * 4 + 4000,
    .sample_byte = 32 * 1000 * 4,
};

static struct fpga_if otdr_interface_32k_2016 = {
    DEFAULT_FPGA_IF,
    .pfun_probe    = _cb_fpga_otdr_probe,
    .pfun_release  = _cb_fpga_otdr_release,
    .private_data  = &data_32k,
    .name          = "this-otdr-32k-2016",
    .pfun_start    = cb_fpga_otdr_start_2016,
    .pfun_isfinish = cb_fpga_otdr_isfinish_2016,
    .pfun_stop     = cb_fpga_otdr_stop,
    .pfun_set_gpio = none_set_gpio,
    .pfun_get_gpio = none_get_gpio,
    .pfun_version  = com_fpga_version,
    // .pfun_read_frame = cb_fpga_read_otdr_data,
    .pfun_read_frame = _cb_fpga_read_otdr_data,
    .pfun_write_regs = cb_fpga_otdr_write_regs_2016,
};

static struct priv_otdr_data data_64k = {
    .cache_len   = 64000 * 4 + 4000,
    .sample_byte = 64 * 1000 * 4,
};

// static struct fpga_if otdr_interface_64k = {
// 	DEFAULT_FPGA_IF,
// 	.pfun_probe      = cb_fpga_otdr_probe,
// 	.private_data    = &data_64k,
// 	.name            = "this-otdr-64k",
// 	.pfun_start      = cb_fpga_otdr_start,
// 	.pfun_isfinish   = cb_fpga_otdr_isfinish,
// 	.pfun_stop       = cb_fpga_otdr_stop,
// 	.pfun_set_gpio   = none_set_gpio,
// 	.pfun_get_gpio   = none_get_gpio,
// 	.pfun_version    = com_fpga_version,
// 	.pfun_read_frame = cb_fpga_read_otdr_data,
// 	.pfun_write_regs = cb_fpga_otdr_write_regs,
// };

static void __attribute__((constructor(INIT_BSP))) this_init()
{
    // printf("otdr_interface_32k_2016 pri %x\r\n", (unsigned int)otdr_interface_32k_2016.private_data);
    fpga_if_register(&otdr_interface_32k_2016);
}
